package cn.tedu.mall.order.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.pojo.domain.CsmallAuthenticationInfo;
import cn.tedu.mall.common.restful.JsonPage;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.front.service.IFrontSkuService;
import cn.tedu.mall.order.service.IOmsCartService;
import cn.tedu.mall.pojo.order.dto.CartAddDTO;
import cn.tedu.mall.pojo.order.dto.CartUpdateDTO;
import cn.tedu.mall.pojo.order.vo.CartStandardVO;
import cn.tedu.mall.pojo.product.vo.SkuStandardVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;

@Service
@Slf4j
public class CartServiceImpl implements IOmsCartService {
    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @DubboReference
    private IFrontSkuService dubboSkuService;
    /**
     * @param cartDTO
     */
    public static final String ORDER_CART_PREFIX="cart:";
    @Override
    public void addCart(CartAddDTO cartDTO) {
        //远程调用获取当前购物车的剩余库存数量
        SkuStandardVO sku = dubboSkuService.getSku(cartDTO.getSkuId());
        Integer stock = sku.getStock();
        if (stock<cartDTO.getQuantity()){
            throw
            new CoolSharkServiceException(ResponseCode.CONFLICT,"库存不够");
        }
        //security 提供了一个线程的对象,保存上下文中认证数据
        Long userId=getUserId();
        String cartKey=ORDER_CART_PREFIX+userId;
        String skuId=cartDTO.getSkuId()+"";
        HashOperations<String, Object, Object> hashOperations = stringRedisTemplate.opsForHash();
        //判断存在 hexists key field
        if (hashOperations.hasKey(cartKey,skuId)){
            //当前不是新增 quantity迭代 hincrby key field num
            Long incrResult = hashOperations.increment(cartKey, skuId, cartDTO.getQuantity());
            if (incrResult>200L || incrResult>stock){
                hashOperations.increment(cartKey,skuId,-cartDTO.getQuantity());
                throw
                new CoolSharkServiceException(ResponseCode.CONFLICT,"禁止购物车添加超过200个");
            }
        }else {
            //新增到hash结构中,但是先获取已有的商品个数 hkeys
            Long size = hashOperations.size(cartKey);//拿到hash里键值对的个数
            if (size==20){
                //没必要考虑并发安全问题
                throw
                new CoolSharkServiceException(ResponseCode.CONFLICT,"购物车商品数量最多20个");

            }
            hashOperations.put(cartKey,cartDTO.getSkuId()+"",cartDTO.getQuantity()+"");
        }
    }

    @Override
    public JsonPage<CartStandardVO> listCarts(Integer page, Integer pageSize) {
        Long userId=getUserId();
        String cartKey=ORDER_CART_PREFIX+userId;
        //操作hash类型
        HashOperations<String, Object, Object> hashOperations = stringRedisTemplate.opsForHash();
        Set<Object> skuIds = hashOperations.keys(cartKey);
        if (skuIds == null || skuIds .size()== 0){
            //返回空购物车数据
            log.debug("当前购物车:{},数据是空",cartKey);
            return JsonPage.nullPage();
        }else {
            //获取所有skuId 远程调用 准备好传递参数
            List<Long> skuidList = new ArrayList<>();
            //将set中的string 转化成long 添加到参数skuidList中
            for (Object skuIdStr : skuIds) {
                Long skuId=Long.parseLong((String)skuIdStr);
                skuidList.add(skuId);
            }
            List<SkuStandardVO> skuStandardVOS =
                    dubboSkuService.listSkuByIds(skuidList);
            if (skuStandardVOS==null || skuStandardVOS.size()==0){
                throw
                new CoolSharkServiceException(ResponseCode.NOT_FOUND,"front没有查询到正确数据");
            }
            //查询到sku商品信息,封装购物车返回结果
            List<CartStandardVO> cartStandardVOS=new ArrayList<>();
            //老老实实,对sku的列表循环,获取需要的属性和值
            //填充cartStandardVOS这个列表;
            for (SkuStandardVO skuStandardVO : skuStandardVOS) {
                //不是BeanUtils,先准备好了返回对象
                CartStandardVO cartStandardVO=new CartStandardVO();
                //title/price/barCode/ 两个对象一一对应
                cartStandardVO.setTitle(skuStandardVO.getTitle());
                cartStandardVO.setPrice(skuStandardVO.getPrice());
                cartStandardVO.setBarCode(skuStandardVO.getBarCode());
                //购物车id/skuId/data/mainPicture/quantity/userId /人为处理甚至需要计算的
                cartStandardVO.setId(getUserId()+":"+skuStandardVO.getId());
                cartStandardVO.setSkuId(skuStandardVO.getId());
                cartStandardVO.setData(skuStandardVO.getSpecifications());
                cartStandardVO.setMainPicture(
                        StringUtils.isEmpty(skuStandardVO.getPictures())==true?
                                null:skuStandardVO.getPictures().split(",")[0]);
                //取一下quantity存储在redis的数据 value
                String quantityStr=
                (String) hashOperations.get(cartKey,skuStandardVO.getId()+"");
                Integer quantity = Integer.parseInt(quantityStr);
                cartStandardVO.setQuantity(quantity);
                cartStandardVO.setUserId(userId);
                cartStandardVOS.add(cartStandardVO);
            }
            //将list对象,包装到一个分页对象里 没有分页数据
            return JsonPage.defaultPage(cartStandardVOS);
        }

    }

    @Override
    public void updateQuantity(CartUpdateDTO cartUpdateDTO) {

        String userIdStr=null;
        String skuIdStr=null;
        try{
            userIdStr=cartUpdateDTO.getId().split(":")[0];
            skuIdStr=cartUpdateDTO.getId().split(":")[1];
        }catch (Exception e){
            throw
            new CoolSharkServiceException(ResponseCode.CONFLICT,"购物车id不规范");
        }
        //准备redis的key值
        String cartKey=ORDER_CART_PREFIX+userIdStr;
        //UNDO 判断购物车是否存在,在继续功能
        //更新购物车redis数据库
        HashOperations<String, Object, Object> hashOperations =
                stringRedisTemplate.opsForHash();
        hashOperations.put(cartKey,skuIdStr,cartUpdateDTO.getQuantity()+"");
    }
    private Long getUserId(){
        //security上下文对象,如果过滤器解析jwt成功,会存储一个认证对象
        SecurityContext context = SecurityContextHolder.getContext();
        //获取认证对象
        UsernamePasswordAuthenticationToken authentication =
                (UsernamePasswordAuthenticationToken) context.getAuthentication();
        if (authentication==null){
            //说明jwt解析有问题,而且security拦截保护,没有限制请求的进入
            throw
                new CoolSharkServiceException(
                        ResponseCode.CONFLICT,"认证对象是空,解析jwt出现错误");
        }
        //拿到principal
        CsmallAuthenticationInfo userInfo=
                (CsmallAuthenticationInfo) authentication.getPrincipal();
        if (userInfo == null){
            //说明jwt解析有问题,而且security拦截保护,没有限制请求的进入
            throw
                    new CoolSharkServiceException(
                            ResponseCode.CONFLICT,"认证逻辑有错误");
        }
        return userInfo.getId();
    }
}
